#pragma once
#include <map>

template <class KEY,class DATA>class ShareMap {
public:
	ShareMap(bool block = true);
	~ShareMap();
	void put(KEY key,DATA item);
	bool erase(KEY key);
	void lock();
	void unLock();
	bool hasData();
	bool hasNext();
	bool has(KEY key);
	typename std::pair<KEY, DATA> next();
	DATA get(KEY key);
	int size();
private:
	std::map<KEY,DATA> map;
	typename std::map<KEY, DATA>::iterator  iter = this->map.begin();
	typename std::map<KEY, DATA>::iterator endIter = this->map.end();
	std::mutex mutex;
	std::condition_variable cond_variable;
	bool block = false;
	bool canRead = true;
};

template <class KEY, class DATA>
inline ShareMap<KEY,DATA>::ShareMap(bool block)
{
	this->block = block;
}

template <class KEY, class DATA>
inline ShareMap<KEY, DATA>::~ShareMap()
{
	this->map.clear();
}

template <class KEY, class DATA>
inline void  ShareMap<KEY, DATA>::lock()
{
	if (this->block) {
		if (this->mutex.try_lock()) {
			this->canRead = false;
			this->mutex.unlock();
		}
	}
}

template<class KEY, class DATA>
inline bool ShareMap<KEY, DATA>::has(KEY key)
{
	while (!this->canRead) {};
	auto iterator = this->map.find(key);
	if (iterator != this->map.end()) {
		return true;
	}
	return false;
}

template <class KEY, class DATA>
inline void ShareMap<KEY, DATA>::unLock()
{
	if (this->block) {
		if (this->mutex.try_lock()) {
			this->canRead = true;
			this->mutex.unlock();
		}
	}
}

template<class KEY, class DATA>
inline bool ShareMap<KEY, DATA>::hasData()
{
	this->iter = this->map.begin();
	this->endIter = this->map.end();
	return (this->size() > 0);
}

template <class KEY, class DATA>
inline int  ShareMap<KEY, DATA>::size()
{
	while (!this->canRead) {
	}
	return this->map.size();
}

template<class KEY, class DATA>
inline void ShareMap<KEY, DATA>::put(KEY key, DATA item)
{
	if (this->has(key)) {
		this->map[key] = item;
	}
	else {
		this->map.insert(std::pair<KEY, DATA>(key, item));
	}
}

template<class KEY, class DATA>
inline bool ShareMap<KEY, DATA>::erase(KEY key)
{
	this->map.erase(key);
	return false;
}

template<class KEY, class DATA>
typename std::pair<KEY, DATA> ShareMap<KEY, DATA>::next()
{
	while (!this->canRead) {
	}
	std::pair<KEY, DATA> valuePair(this->iter->first, this->iter->second);
	this->iter++;
	return valuePair;
}

template<class KEY, class DATA>
inline bool ShareMap<KEY, DATA>::hasNext()
{
	while (!this->canRead) {
	}
	return this->iter != this->endIter;
}

template<class KEY, class DATA>
inline DATA ShareMap<KEY, DATA>::get(KEY key)
{
	while (!this->canRead) {
	}
	return this->map[key];
}
